
#include "Game.h"
#include "Interface.h"
#include "Civilization.h"
#include "Technology.h"
#include "Terrain.h"
#include "Crash.h"

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// InitializeGame /////////////////////////////////////////////////////////////////////////////////////////////////
// sets all the variables in the game to initial values ///////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void InitializeGame()
{
	game.worldmap = NULL;
	game.improv = NULL;
	game.bonusTerrain = NULL;
	game.civ_names = NULL;
	game.city_names = NULL;
	game.unitpic = NULL;
	game.backpic = NULL;
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// CreateGame /////////////////////////////////////////////////////////////////////////////////////////////////////
// creates a new game or laods an existing one ////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void CreateGame()
{
	//start the game with the start screen
	DrawStartPage();
	FontSetSys(F_4x6);
	
	// for the FOR statements
	int loop;
	
	// Sets the array values for all the variables
	LoadGameData();
	
	// New Game or Load Game
	char newGame = 0;
	DrawStr(30, 75, "New Game", A_NORMAL);
	DrawStr(90, 75, "Load Game", A_NORMAL);
	
	int key = 0;
	while(key != KEY_ENTER && key != KEY_ESC)
	{
		DrawLine(30 + 60*newGame, 82, 65 + 60*newGame, 82, A_XOR);
		key = ngetchx();
		DrawLine(30 + 60*newGame, 82, 65 + 60*newGame, 82, A_XOR);
		
		if(key == KEY_LEFT && --newGame < 0) newGame = 1;
		if(key == KEY_RIGHT && ++newGame > 1) newGame = 0;
	}
	
	if(key == KEY_ESC) ExitCiv();
	
	newGame = 1 - newGame;
	
	if(newGame) NewGame();
	else LoadScenario(0);
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// DrawCheck //////////////////////////////////////////////////////////////////////////////////////////////////////
// draws a check sign at the given coordinates ////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void DrawCheck(int x, int y)
{
	DrawPix(x  , y+2, A_NORMAL);
	DrawPix(x+1, y+3, A_NORMAL);
	DrawPix(x+2, y+2, A_NORMAL);
	DrawPix(x+3, y+1, A_NORMAL);
	DrawPix(x+4, y  , A_NORMAL);
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// ProcessTurn ////////////////////////////////////////////////////////////////////////////////////////////////////
// does one complete turn /////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void ProcessTurn()
{
	// Do all the player movement/actions
	while(!MoveMainCursor())
		if(!MainMenu()) ExitCiv();
	
	// do the computer players
	ProcessAI();
	
	// shows the progress bar for new of turn
	ClrScr();
	DrawStr(60, 32, "New Turn...", A_NORMAL);
	DrawLine( 20, 40, 140, 40, A_NORMAL);
	DrawLine( 20, 50, 140, 50, A_NORMAL);
	DrawLine( 20, 40,  20, 50, A_NORMAL);
	DrawLine(140, 40, 140, 50, A_NORMAL);
	DrawStr(40, 55, "Technology", A_NORMAL);
	DrawStr(40, 65, "Cities", A_NORMAL);
	DrawStr(40, 75, "Units", A_NORMAL);
	
	// updates the cities, units, and technology for all civilizations
	int i, x = 20;
	for(i = 0; i < civNumb; i++)
	{
		UpdateTechnology(i);
		DrawCheck(35, 55);	
		UpdateCities(i);
		DrawCheck(35, 65);		
		UpdateUnits(i);
		DrawCheck(35, 75);	
		
		if(i == 0)
		{
			// shows the progress bar for new of turn
			ClrScr();
			DrawStr(60, 32, "New Turn...", A_NORMAL);
			DrawLine( 20, 40, 140, 40, A_NORMAL);
			DrawLine( 20, 50, 140, 50, A_NORMAL);
			DrawLine( 20, 40,  20, 50, A_NORMAL);
			DrawLine(140, 40, 140, 50, A_NORMAL);
			DrawStr(40, 55, "Technology", A_NORMAL);
			DrawStr(40, 65, "Cities", A_NORMAL);
			DrawStr(40, 75, "Units", A_NORMAL);
		}

		// increase progress bar percent
		int _x = (i+1) * 120 / civNumb + 20;
		while(x < _x-1)
			DrawLine(++x, 41, x, 49, A_NORMAL);
		Clr(35, 54, 39, 78);
	}
	
	// update turn counter
	game.turn++;

	if(game.turn > game.maxTurns) ExitCiv();
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// GetCursor //////////////////////////////////////////////////////////////////////////////////////////////////////
// gets the cursor on the global map //////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
int GetCursorX()
{
	return game.cursor[0] + 5*game.qX;
}
int GetCursorY()
{
	return game.cursor[1] + 3*game.qY;
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// LoadGameData ///////////////////////////////////////////////////////////////////////////////////////////////////
// loads all the data from the civdata.civ file ///////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void LoadGameData()
{	
	FILE *f = fopen("civdata","rb");
 	if(f == NULL) Crash(MISSING_FILE, "civdata.civ file");
	
	// version
	char version[7];
	fread(version, 7*sizeof(char),1,f);
	if(version[0] != 'v')
	{
		fclose(f);
		Crash(DIALOG, "civdata version too old.");
	}
 	
 	// allocate memory
 	game.civ_names = (char*)Malloc(11*14*sizeof(char));
 	game.city_names = (char*)Malloc(11*15*16*sizeof(char));
	game.unitpic = (unsigned short int*)Malloc(12*9*sizeof(unsigned short int));
	game.backpic = (unsigned short int*)Malloc(8*9*sizeof(unsigned short int));
	if(game.civ_names == NULL || game.city_names == NULL ||
		 game.unitpic == NULL   || game.backpic == NULL)
	{
		fclose(f);
		Crash(MEMORY, "Civ Data");
	}
 	
 	// civ names
	fread(game.civ_names, 11*14*sizeof(char),1,f);
	
	// city names
	fread(game.city_names, 11*15*16*sizeof(char),1,f);
	
	// sprites
	fread(game.unitpic, 12*9*sizeof(unsigned short int),1,f);
	fread(game.backpic, 8*9*sizeof(unsigned short int),1,f);
	
	// structs
	fread(_units, 19*sizeof(Unit),1,f);
	fread(terrain, 8*sizeof(Terrain),1,f);
	fread(tBonus, 21*sizeof(TBonus),1,f);
	fread(buildings, 67*sizeof(Building),1,f);
	fread(buildngsDesc, 67*4*12*sizeof(char),1,f);
	fread(techs, 90*sizeof(Technology),1,f);
	
	fclose(f);
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// FreeGameData ///////////////////////////////////////////////////////////////////////////////////////////////////
// frees all the data from the civdata.civ file ///////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void FreeGameData()
{
	// Other structures
	Delete(game.civ_names);
	Delete(game.city_names);
	Delete(game.unitpic);
	Delete(game.backpic);
		
	// free all the left over memory	
	if(game.worldmap != NULL)
	{
		Free(game.worldmap);
		if(game.improv != NULL) Free(game.improv);
		if(game.bonusTerrain != NULL) Free(game.bonusTerrain);
		
		FreeCivData();
	}
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// NewGame ////////////////////////////////////////////////////////////////////////////////////////////////////////
// creates a new game /////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void NewGame()
{
	// length of the game
	game.turn = 1;
	#ifdef DEBUG
	game.maxTurns = 500;
	#else
	game.maxTurns = GetMaxTurns();
	#endif
	
	// creates civilizations
	#ifdef DEBUG
	civNumb = 2;
	#else 
	civNumb = GetNumOfCivs();
	#endif
	
	// Allocates memory for the arrays
	civilization = (Civ*)Malloc(civNumb * sizeof(Civ));
	AssertAllocate(civilization);

	aiCivs = (AI*)Malloc((civNumb-1) * sizeof(AI));
	AssertAllocate(aiCivs);
		
	// populates the array
	int loop;
	for(loop = 0; loop < civNumb; loop++)
	  NewCiv(loop);
	  
	// Creates the map
	LoadMap();
		
	// populates the array
	int size = game.mapWidth * game.mapHeight / 8 + 1;
	for(loop = 0; loop < civNumb; loop++)
	{
	  civilization[loop].fog = (BitArray*)Malloc(size * sizeof(BitArray));
		AssertAllocate(civilization[loop].fog);
	  
		int loop2;
		for(loop2 = 0; loop2 < size; loop2++)
		{
			civilization[loop].fog[loop2] = 0;
		}
	}
	
	// Bonus Terrain
	randomize();
	GenerateBonusTerrain(__randseed);
	
	// create starting positions
	SetupCivs();
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// SetupCivs //////////////////////////////////////////////////////////////////////////////////////////////////////
// creates random starting positions for all civilizations ////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void SetupCivs()
{
	int x[civNumb], y[civNumb];
	char i = 0;
	
	while(i < civNumb)
	{
		int _x = random(game.mapWidth-1);
		int _y = random(game.mapHeight-1);
		
		while(Worldmap(_y,_x)-1 == WATER) 
		{ 
			_x = random(game.mapWidth-1); 
			_y = random(game.mapHeight-1); 
		}
		
		int j;
		bool retry = 0;
		for(j = 0; j < i && !retry; j++)
		{
			if(abs(_x-x[j]) < 5 || abs(_y-y[j]) < 4)
				retry = 1;
		}
		
		if(retry == 0)
		{
			x[i] = _x;
			y[i] = _y;
			i++;
		}		
	}
	
	// gives each civ some units
	for(i = 0; i < civNumb; i++)
	{
		NewUnit(i, SETTLER, x[i]+1, y[i]+1, REGULAR);
		NewUnit(i, WARRIOR, x[i]+1, y[i]+1, REGULAR);
	}
	
	// sets the ai up
	for(i = 0; i < civNumb-1; i++)
	{
		aiCivs[i].type = random(4);
		aiCivs[i].autoSettlers = 0;
		aiCivs[i].attitude = (char*)Malloc(civNumb * sizeof(char));
		
		char j;
		for(j = 0; j < civNumb; j++)
			aiCivs[i].attitude[j] = 50;
	}
	
	// set the cursor on player 1's starting position
	SetCursor(x[0]+1, y[0]+1);
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// GenerateBonusTerrain ///////////////////////////////////////////////////////////////////////////////////////////
// creates and populates the bonusTerrain array based off a random seed ///////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void GenerateBonusTerrain(long seed)
{
	game.randomSeed = seed;
	__randseed = seed;

	int i;
	for(i = 0; i < game.mapWidth * game.mapHeight; i++)
	{
		if(random(7) == 0)
		{
			int t = game.worldmap[i]-1;
			game.bonusTerrain[i] = tIndex[t][0] + random(tIndex[t][1]);
		}
		else game.bonusTerrain[i] = -1;
	}
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// ProcessAI //////////////////////////////////////////////////////////////////////////////////////////////////////
// provides computer control of other civilizations ///////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void ProcessAI()
{
	// shows the progress bar for ai
	ClrScr();
	DrawStr(60, 22, "AI progress...", A_NORMAL);
	DrawLine( 20, 30, 140, 30, A_NORMAL);
	DrawLine( 20, 40, 140, 40, A_NORMAL);
	DrawLine( 20, 30,  20, 40, A_NORMAL);
	DrawLine(140, 30, 140, 40, A_NORMAL);
	
	DrawLine( 20, 60, 140, 60, A_NORMAL);
	DrawLine( 20, 70, 140, 70, A_NORMAL);
	DrawLine( 20, 60,  20, 70, A_NORMAL);
	DrawLine(140, 60, 140, 70, A_NORMAL);
	int x = 20;
	
	char i;
	for(i = 1; i < civNumb; i++)
	{
		//AI_DoCities(i);
		AI_DoUnits(i);
		
		// increase progress bar percent
		int _x = i * 120 / (civNumb-1) + 20;
		while(x < _x - 1)
			DrawLine(++x, 31, x, 39, A_NORMAL);
	}
}
